//
//  TabView.swift
//  
//
//  Created by 孙长坦 on 2022/4/28.
//

import Foundation
import UIKit
import RxRelay

public class TabView: UIView {
    private static let startItemViewTag = 100000
    
    public let contentView = UIScrollView()
    
    public weak var dataSource: TabViewDataSource? {
        didSet {
            addItemView(index: pagePosition)
        }
    }
    
    public private(set) var pagePosition: Int = 0 {
        didSet {
            pagePositionObservable.accept(pagePosition)
        }
    }
    
    public let pagePositionObservable = PublishRelay<Int>()
    
    public init(pagePosition: Int = 0, frame: CGRect = .zero) {
        self.pagePosition = pagePosition
        
        super.init(frame: frame)
        
        contentView.delegate = self
        
        contentView.isPagingEnabled = true
        addSubview(contentView)
        
        addItemView(index: pagePosition)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    public override func layoutSubviews() {
        super.layoutSubviews()
        
        layoutContentView()
    }
    
    private func layoutContentView() {
        contentView.frame = bounds
        
        guard let dataSource = dataSource else {
            return
        }
        
        let itemsCount = dataSource.numberOfItems(in: self)
        
        contentView.contentSize = CGSize(width: contentView.bounds.width * CGFloat(itemsCount),
                                         height: contentView.bounds.height)
        contentView.contentOffset = CGPoint(x: contentView.bounds.width * CGFloat(pagePosition), y: 0)
        
        contentView.subviews.forEach { subview in
            let index = subview.tag - TabView.startItemViewTag
            guard index >= 0, index < itemsCount else {
                return
            }
            
            subview.frame = CGRect(x: contentView.bounds.width * CGFloat(index),
                                   y: 0,
                                   width: contentView.bounds.width,
                                   height: contentView.bounds.height)
        }
    }
    
    public func set(pagePosition: Int, animated: Bool) {
        guard self.pagePosition != pagePosition else {
            return
        }
        
        addItemView(index: pagePosition)
        
        let x = contentView.bounds.width * CGFloat(pagePosition)

        if contentView.bounds.width != 0, contentView.contentOffset.x != x {
            contentView.setContentOffset(CGPoint(x: x, y: 0), animated: animated)
        } else {
            self.pagePosition = pagePosition
        }
    }
    
    private func addItemView(index: Int){
        guard let dataSource = dataSource else {
            return
        }
        
        guard contentView.subviews.first(where: { $0.tag == TabView.startItemViewTag + index }) == nil else {
            return
        }
        
        let itemView = dataSource.tabView(self, itemForIndex: index)
        itemView.tag = TabView.startItemViewTag + index
        contentView.addSubview(itemView)
        
        setNeedsLayout()
    }
}

extension TabView: UIScrollViewDelegate {
    
    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
        
    }
    
    public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        setPagePosition(scrollView)
    }
    
    public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        setPagePosition(scrollView)
    }
    
    private func setPagePosition(_ scrollView: UIScrollView) {
        guard let dataSource = dataSource else {
            return
        }
        
        let itemsCount = dataSource.numberOfItems(in: self)
        let pagePosition = Int(ceil(scrollView.contentOffset.x / scrollView.bounds.width))
        set(pagePosition: pagePosition >= itemsCount ? itemsCount - 1 : pagePosition, animated: false)
    }
}
